module repository.TeleplayRepo;

import std.stdio;
import std.format;

import d2sqlite3;

import model.Teleplay;
import model.TeleplayVlink;
import utils.ConstValue;

// 电视剧仓储类
class TeleplayRepo
{
    Database db;
    this ()
    {
        db = Database(Const.connStr);
    }

    ~this ()
    {
        db.close();
    }

    /** 
     * 添加电视剧
     * Params:
     *   teleplay  =  `Teleplay `  =  Teleplay实例
     * Returns: bool
     */
    bool addTeleplay (Teleplay teleplay)
    {
        Statement statement1 = db.prepare("SELECT t.id FROM teleplay t WHERE t.id = :id LIMIT 1;");
        statement1.bind(":id", teleplay.id);
        ResultRange res = statement1.execute();
        // 记录已存在
        if (!res.empty)
        {
            return false;
        }

        Statement statement2 = db.prepare("INSERT INTO teleplay (id, name, url, category, region, year, actors, director, intro, img, comment) VALUES (:id, :name, :url, :category, :region, :year, :actors, :director, :intro, :img, :comment)");
        statement2.bindAll(teleplay.id, teleplay.name, teleplay.url, teleplay.category, teleplay.region, teleplay.year, teleplay
                .actors, teleplay.director, teleplay.intro, teleplay.img, teleplay.comment);
        statement2.execute();
        return db.changes > 0;
    }

    /** 
     * 批量添加电视剧
     * Params:
     *   teleplayList  =  `Teleplay[]`  =   待添加的电视剧列表
     * Returns: bool
     */
    bool addTeleplayBatch (Teleplay[] teleplayList)
    {
        import std.format : format;

        auto total = teleplayList.length;
        string sql = "INSERT INTO teleplay (id, name, url, category, region, year, actors, director, intro, img, comment) VALUES ";
        string sqlLeft;
        foreach (t; teleplayList)
        {
            sqlLeft = format(`("%s","%s","%s","%s","%s",%d,"%s","%s","%s","%s","%s")`, t.id, t.name, t.url, t
                    .category, t.region, t.year, t.actors, t.director, t.intro, t.img, t.comment);
            sql ~= sqlLeft;
        }
        sql ~= ";";

        db.execute(sql);
        int ch = db.changes;
        if (0 < ch && ch <= total)
        {
            return true;
        }
        return false;
    }

    /** 
     * 删除电视剧
     * Params:
     *   teleplayId   =  `string`  =  id值
     * Returns: bool
     */
    bool removeTeleplay (string teleplayId)
    {
        Statement statement = db.prepare("DELETE FROM teleplay WHERE id=:id");
        statement.bind(":id", teleplayId);
        statement.execute();
        return db.changes > 0;
    }

    /** 
    * 更新电视剧信息
    * Params:
    *   teleplayId   =   `string`  =  id值
    *   teleplay  =  `Teleplay`  =   Teleplay实例
    * Returns: bool
    */
    bool updateTeleplay (string teleplayId, Teleplay teleplay)
    {
        import std.conv : to;
        import std.digest : toHexString;
        import std.digest.md : md5Of;

        string newid = to!string(toHexString(md5Of(teleplay.name)));

        Statement statement = db.prepare("UPDATE teleplay SET id=:newid, name=:name, url=:url, category=:category, region=:region, year=:year, actors=:actors, director=:director, intro=:intro, img=:img, comment=:comment WHERE id=:id");
        statement.bindAll(newid, teleplay.name, teleplay.url, teleplay.category, teleplay.region, teleplay.year, teleplay
                .actors, teleplay
                .director, teleplay.intro, teleplay.img, teleplay.comment, teleplayId);
        statement.execute();
        return db.changes > 0;
    }

    /** 
     * 获取电视剧列表数据
     * Returns: Teleplay[]
     */
    Teleplay[] getTeleplayList ()
    {
        ResultRange results = db.execute(
            "SELECT id, name, url, category, region, year, actors, director, intro, img, comment FROM teleplay ORDER BY year DESC");

        Teleplay[] teleplayList = [];
        if (results.empty)
        {
            return teleplayList;
        }
        foreach (Row row; results)
        {
            auto id = row["id"].as!string;
            auto name = row["name"].as!string;
            auto url = row["url"].as!string;
            auto category = row["category"].as!string;
            auto region = row["region"].as!string;
            auto year = row["year"].as!uint;
            auto actors = row["actors"].as!string;
            auto director = row["director"].as!string;
            auto intro = row["intro"].as!string;
            auto img = row["img"].as!string;
            auto comment = row["comment"].as!string;

            teleplayList ~= new Teleplay(id, name, url, category, region, year, actors, director, intro, img, comment);
        }

        return teleplayList;
    }

    /** 
     * 分页获取电视剧列表数据
     * Params:
     *   pageSize  =  `uint`  =   页大小
     *   pageNum  =  `uint`  =   页码
     * Returns: Teleplay[]
     */
    Teleplay[] getTeleplayListPaging (uint pageSize, uint pageNum)
    {
        if (pageSize <= 4)
        {
            pageSize = 8;
        }
        if (pageNum <= 0)
        {
            pageNum = 1;
        }
        uint offset = (pageNum - 1) * pageSize;
        Statement statement = db.prepare("SELECT id, name, url, category, region, year, actors, director, intro, img, comment FROM teleplay as t ORDER BY t.year DESC LIMIT :pageSize OFFSET :offset;");
        statement.bindAll(pageSize, offset);
        ResultRange results = statement.execute();
        scope (exit)
        {
            statement.reset();
        }

        Teleplay[] teleplayList = [];
        if (results.empty)
        {
            return teleplayList;
        }

        foreach (Row row; results)
        {
            auto id = row["id"].as!string;
            auto name = row["name"].as!string;
            auto url = row["url"].as!string;
            auto category = row["category"].as!string;
            auto region = row["region"].as!string;
            auto year = row["year"].as!uint;
            auto actors = row["actors"].as!string;
            auto director = row["director"].as!string;
            auto intro = row["intro"].as!string;
            auto img = row["img"].as!string;
            auto comment = row["comment"].as!string;

            teleplayList ~= new Teleplay(id, name, url, category, region, year, actors, director, intro, img, comment);
        }

        return teleplayList;
    }

    /** 
     * 获取总记录数
     * Returns: uint
     */
    uint getTotalCount ()
    {
        uint total = db.execute("SELECT COUNT(id) FROM teleplay;").oneValue!uint;
        return total;
    }

    /** 
     * 获取一个电视剧
     * Params:
     *   teleplayId  =  `string`  =  id值
     * Returns: Teleplay
     */
    Teleplay getOneTeleplay (string teleplayId)
    {
        Statement statement = db.prepare(
            "SELECT id, name, url, category, region, year, actors, director, intro, img, comment FROM teleplay WHERE id=:id LIMIT 1");

        statement.bind(":id", teleplayId);
        ResultRange results = statement.execute();
        scope (exit)
        {
            statement.reset();
        }

        if (results.empty)
        {
            return null;
        }
        auto row = results.front;
        auto id = row["id"].as!string;
        auto name = row["name"].as!string;
        auto url = row["url"].as!string;
        auto category = row["category"].as!string;
        auto region = row["region"].as!string;
        auto year = row["year"].as!uint;
        auto actors = row["actors"].as!string;
        auto director = row["director"].as!string;
        auto intro = row["intro"].as!string;
        auto img = row["img"].as!string;
        auto comment = row["comment"].as!string;

        return new Teleplay(id, name, url, category, region, year, actors, director, intro, img, comment);
    }

    /** 
     * 获取某个电视剧的集数链接
     * Params:
     *   teleplayId  =  `string`  =  电视剧id值
     * Returns: TeleplayVlink[]
     */
    TeleplayVlink[] getTeleplayVideoLinks (string teleplayId)
    {
        Statement statement = db.prepare(
            "SELECT id, name, url, real_url FROM teleplay_vlinks WHERE teleplay_id=:id");
        statement.bind(":id", teleplayId);
        ResultRange results = statement.execute();
        scope (exit)
        {
            statement.reset();
        }

        TeleplayVlink[] list = [];
        if (results.empty)
        {
            return list;
        }

        foreach (Row row; results)
        {
            auto id = row["id"].as!uint;
            auto name = row["name"].as!string;
            auto url = row["url"].as!string;
            auto real_url = row["real_url"].as!string;

            list ~= new TeleplayVlink(id, name, url, real_url);
        }

        return list;
    }

    /** 
     * 获取电视剧全部年份
     * Returns: uint[]
     */
    uint[] getTeleplayYears ()
    {
        uint[] years = [];
        ResultRange results = db.execute("SELECT DISTINCT year FROM teleplay;");
        if (results.empty)
        {
            return years;
        }
        foreach (Row row; results)
        {
            uint year = row["year"].as!uint;
            years ~= year;
        }

        return years;
    }

    /** 
     * 写评语
     * Params:
     *   id  =  `string`
     *   comment  =  `string`
     * Returns: bool
     */
    bool doComment (string id, string comment)
    {
        Statement statement = db.prepare("UPDATE teleplay SET comment=:comment WHERE id=:id");
        statement.bind(":comment", comment);
        statement.bind(":id", id);
        statement.execute();
        return db.changes > 0;
    }
}
